package com.chat.wesocket.handler;

import com.alibaba.fastjson2.JSON;
import com.chat.security.entity.JWTLoginUser;
import com.chat.wesocket.constant.WsConstant;
import com.chat.wesocket.entity.WsMessage;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class WsHandler implements WebSocketHandler {
    private final Map<String, WebSocketSession> loginUserSessions = new ConcurrentHashMap<>(64);

    public WebSocketSession isOnline(String userName) {
        return loginUserSessions.get(userName);
    }
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        final JWTLoginUser jwtLoginUser = (JWTLoginUser) session.getAttributes().get(WsConstant.WS_LOGIN_USER_KEY);
        loginUserSessions.put(jwtLoginUser.getUserName(),session);
    }

    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        final WsMessage wsMessage = JSON.parseObject(message.getPayload().toString(), WsMessage.class);
        switch (wsMessage.getEventName()){
            case WsMessage.ON_CANDIDATE:handleCandidate(wsMessage);break;
            case WsMessage.ON_NEGOTIATION_OFFER:handleNegotiationOffer(wsMessage);break;
            case WsMessage.ON_NEGOTIATION_ANSWER:handleNegotiationAnswer(wsMessage);break;
        }
    }

    private void handleNegotiationOffer(WsMessage wsMessage) {
        final String to = wsMessage.get("to").toString();
        wsMessage.put(WsMessage.EVENT_NAME,WsMessage.EVENT_NEGOTIATION_OFFER);
        final WebSocketSession online = isOnline(to);
        if (online != null) {
            try {
                synchronized (online) {
                    online.sendMessage(wsMessage.toMessage());
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    private void handleNegotiationAnswer(WsMessage wsMessage) {
        final String to = wsMessage.get("to").toString();
        wsMessage.put(WsMessage.EVENT_NAME,WsMessage.EVENT_NEGOTIATION_ANSWER);
        final WebSocketSession online = isOnline(to);
        if (online != null) {
            try {
                synchronized (online) {
                    online.sendMessage(wsMessage.toMessage());
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void handleCandidate(WsMessage wsMessage) {
        final String to = wsMessage.get("to").toString();
        wsMessage.put(WsMessage.EVENT_NAME,WsMessage.EVENT_CANDIDATE);
        final WebSocketSession online = isOnline(to);
        if (online != null) {
            try {
                synchronized (online) {
                    online.sendMessage(wsMessage.toMessage());
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {

    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        final JWTLoginUser jwtLoginUser = (JWTLoginUser) session.getAttributes().get(WsConstant.WS_LOGIN_USER_KEY);
        loginUserSessions.remove(jwtLoginUser.getUserName());
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }
}
